﻿using Koala.Pro.Common;
using Koala.Pro.Core.Models;
using Koala.Pro.Core;
using Koala.Pro.Helpers;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Koala.Pro.Core.Dto;

namespace Koala.Pro.Services
{
    public class OuService : MyCrudService<OuInfo, int, OuPagedDto>, IOuService, IMyCrudService<OuInfo, int, OuPagedDto>, ITransientDependency, IDependency
    {
        private IUserService _userService;

        public OuService(IApiUserSession currentApiUser, IUserService userService)
        {
            base.CurrentApiUser = currentApiUser;
            _userService = userService;
        }

        public override Task<Dictionary<string, string>> GetColumnNameAlias()
        {
            return Task.FromResult(new Dictionary<string, string>
        {
            { "PID", "父ID" },
            { "HandNo", "机构编码" },
            { "Name", "机构名称" },
            { "SortCode", "排序码" },
            { "Category", "机构分类" },
            { "Address", "机构地址" },
            { "OuterPhone", "外线电话" },
            { "InnerPhone", "内线电话" },
            { "Note", "备注" },
            { "Creator", "创建人" },
            { "Creator_ID", "创建人ID" },
            { "CreateTime", "创建时间" },
            { "Editor", "编辑人" },
            { "Editor_ID", "编辑人ID" },
            { "EditTime", "编辑时间" },
            { "Deleted", "是否已删除" },
            { "Enabled", "有效标志" },
            { "Company_ID", "所属公司ID" },
            { "CompanyName", "所属公司名称" }
        });
        }

        protected override ISugarQueryable<OuInfo> CreateFilteredQueryAsync(OuPagedDto input)
        {
            return base.CreateFilteredQueryAsync(input).WhereIF(input.ExcludeId.HasValue, (OuInfo t) => (int?)t.Id != input.ExcludeId).WhereIF(input.PID.HasValue, (OuInfo s) => s.PID == input.PID)
                .WhereIF(!input.HandNo.IsNullOrWhiteSpace(), (OuInfo t) => t.HandNo.Contains(input.HandNo))
                .WhereIF(!input.Name.IsNullOrWhiteSpace(), (OuInfo t) => t.Name.Contains(input.Name))
                .WhereIF(!input.SortCode.IsNullOrWhiteSpace(), (OuInfo t) => t.SortCode.Contains(input.SortCode))
                .WhereIF(!input.Category.IsNullOrWhiteSpace(), (OuInfo t) => t.Category.Contains(input.Category))
                .WhereIF(!input.Address.IsNullOrWhiteSpace(), (OuInfo t) => t.Address.Contains(input.Address))
                .WhereIF(!input.OuterPhone.IsNullOrWhiteSpace(), (OuInfo t) => t.OuterPhone.Contains(input.OuterPhone))
                .WhereIF(!input.InnerPhone.IsNullOrWhiteSpace(), (OuInfo t) => t.InnerPhone.Contains(input.InnerPhone))
                .WhereIF(!input.Note.IsNullOrWhiteSpace(), (OuInfo t) => t.Note.Contains(input.Note))
                .WhereIF(!input.Creator.IsNullOrWhiteSpace(), (OuInfo t) => t.Creator.Contains(input.Creator))
                .WhereIF(!input.Creator_ID.IsNullOrWhiteSpace(), (OuInfo t) => t.Creator_ID.Contains(input.Creator_ID))
                .WhereIF(input.CreateTimeStart.HasValue, (OuInfo s) => s.CreateTime >= input.CreateTimeStart.Value)
                .WhereIF(input.CreateTimeEnd.HasValue, (OuInfo s) => s.CreateTime <= input.CreateTimeEnd.Value)
                .WhereIF(!input.Editor.IsNullOrWhiteSpace(), (OuInfo t) => t.Editor.Contains(input.Editor))
                .WhereIF(!input.Editor_ID.IsNullOrWhiteSpace(), (OuInfo t) => t.Editor_ID.Contains(input.Editor_ID))
                .WhereIF(input.EditTimeStart.HasValue, (OuInfo s) => s.EditTime >= input.EditTimeStart.Value)
                .WhereIF(input.EditTimeEnd.HasValue, (OuInfo s) => s.EditTime <= input.EditTimeEnd.Value)
                .WhereIF(input.Deleted.HasValue, (OuInfo s) => s.Deleted == input.Deleted)
                .WhereIF(input.Enabled.HasValue, (OuInfo s) => s.Enabled >= (int?)input.Enabled.Value)
                .WhereIF(!input.Company_ID.IsNullOrWhiteSpace(), (OuInfo t) => t.Company_ID.Equals(input.Company_ID))
                .WhereIF(!input.CompanyName.IsNullOrWhiteSpace(), (OuInfo t) => t.CompanyName.Contains(input.CompanyName));
        }

        protected override ISugarQueryable<OuInfo> ApplyDefaultSorting(ISugarQueryable<OuInfo> query)
        {
            return query.OrderBy((OuInfo s) => s.CreateTime, OrderByType.Desc);
        }

        public async Task<List<OuInfo>> GetOUsByUser(int userID)
        {
            return await (from t in base.Client.Queryable((OuInfo t, OU_UserInfo m) => t.Id == m.Ou_ID && m.User_ID == userID)
                          select (t) into t
                          orderby t.CreateTime
                          select t).ToListAsync();
        }

        public async Task<List<OuInfo>> GetTopGroup()
        {
            return (await GetAllAsync((OuInfo s) => s.PID == (int?)(-1) || !s.PID.HasValue))?.Items.ToList();
        }

        public async Task<List<OuInfo>> GetAllByParent(int parentId)
        {
            return GetLinks(await (from t in base.Client.GetSimpleClient<OuInfo>().AsSugarClient().Queryable<OuInfo>()
                                   where t.Deleted != (int?)1
                                   orderby t.PID
                                   orderby t.Name
                                   select t).ToTreeAsync((OuInfo t) => t.Children, (OuInfo t) => t.PID, parentId)).Select((Func<OuInfo, OuInfo>)((OuInfo s) => s)).ToList();
        }

        public async Task<List<OuInfo>> GetTreeByID(int parentId)
        {
            return await (from t in base.Client.GetSimpleClient<OuInfo>().AsSugarClient().Queryable<OuInfo>()
                          where t.Deleted != 1
                          orderby t.PID
                          orderby t.Name
                          select t).ToTreeAsync((OuInfo t) => t.Children, (OuInfo t) => t.PID, parentId);
        }

        public async Task<List<OuInfo>> GetGroupCompany()
        {
            return (await GetAllAsync((OuInfo s) => (s.Category == "公司" || s.Category == "集团") && s.Deleted != (int?)1))?.Items.ToList();
        }

        public async Task<List<OuInfo>> GetGroupCompanyTree()
        {
            return await (from s in base.Client.GetSimpleClient<OuInfo>().AsQueryable()
                          where s.Category == "公司" || s.Category == "集团"
                          select s into t
                          where t.Deleted != (int?)1
                          orderby t.CreateTime
                          select t).ToTreeAsync(rootValue: -1, childListExpression: (OuInfo t) => t.Children, parentIdExpression: (OuInfo t) => t.PID);
        }

        public async Task<List<OuInfo>> GetAllCompany(int groupId)
        {
            return (await GetAllAsync((OuInfo s) => s.Category == "公司" && s.PID == (int?)groupId))?.Items.ToList();
        }

        public async Task<List<OuInfo>> GetOUsByRole(int roleID)
        {
            return await (from t in base.Client.Queryable((OuInfo t, OU_RoleInfo m) => t.Id == m.Ou_ID && m.Role_ID == roleID)
                          orderby t.Name
                          select t).ToListAsync();
        }

        public async Task<bool> SetDeletedFlag(int id, bool deleted = true)
        {
            bool result = false;
            int intDeleted = (deleted ? 1 : 0);
            OuInfo ouInfo = await GetAsync(id);
            if (ouInfo != null)
            {
                ouInfo.Deleted = intDeleted;
                result = await UpdateAsync(ouInfo);
            }
            return result;
        }

        public async Task<OuInfo> FindByName(string name)
        {
            return await GetFirstAsync((OuInfo s) => s.Name == name);
        }

        public async Task<bool> AddUser(int userID, int ouID)
        {
            OU_UserInfo insertObj = new OU_UserInfo
            {
                User_ID = userID,
                Ou_ID = ouID
            };
            return await base.Client.GetSimpleClient<OU_UserInfo>().InsertAsync(insertObj);
        }

        public async Task<bool> RemoveUser(int userID, int ouID)
        {
            return await base.Client.GetSimpleClient<OU_UserInfo>().DeleteAsync((OU_UserInfo s) => s.User_ID == userID && s.Ou_ID == ouID);
        }

        private IEnumerable<OuInfo> GetLinks(IEnumerable<OuInfo> list)
        {
            foreach (OuInfo node in list)
            {
                yield return node;
                foreach (OuInfo link in GetLinks(node.Children))
                {
                    yield return link;
                }
            }
        }

        public async Task<string> GetName(int id)
        {
            return (await GetAsync(id))?.Name;
        }

        public async Task<List<TreeNodeItem>> GetOUCategorysDictJson()
        {
            List<TreeNodeItem> list = new List<TreeNodeItem>();
            string[] memberNames = EnumHelper.GetMemberNames<OUCategoryEnum>();
            foreach (string text in memberNames)
            {
                list.Add(new TreeNodeItem(text));
            }
            return await Task.FromResult(list);
        }
    }
}
